Módulo 2: Padrões Pontuais

A compreensão do lugar na vigilância em saúde é essencial para entender a distribuição e a dinâmica de doenças e outros fenômenos de saúde. Na análise de padrões pontuais — isto é, conjuntos de casos representados por pontos no mapa — eles identificam rapidamente localidades de risco elevado, passíveis de intervenção. A simples sobreposição desses pontos revela se os eventos se agregam, se dispersam ou se distribuem ao acaso; quando surgem aglomerações inesperadas, eles acionam investigações de campo e direcionam equipes e insumos para as áreas críticas. Esse olhar do espaço permite que a Vigilância em Saúde seja mais proativa, prevendo surtos e epidemias, otimizando recursos e melhorando a resposta a emergências de saúde pública.

No módulo 1 deste curso você aprendeu sobre os dados espaciais e como eles podem ser representados em um mapa. Agora, vamos nos aprofundar na análise de padrões pontuais. Vamos explorar como esses dados podem ser utilizados para entender a distribuição de eventos no espaço e como isso pode ser aplicado na vigilância em saúde.

Vamos lá?

O que são Padrões Pontuais?

Como vimos no módulo anterior, o ponto é o tipo mais simples de dado espacial e possui um par de coordenadas (X,Y) em um mapa ou plano. Vejamos abaixo um exemplo simples de tabela contendo dados de pontos:

Evento Coordenada X Coordenada Y
1 4.30 2.45
2 5.39 3.35
3 4.10 3.50

Ao analisar a localização de pontos no espaço, é possível identificar padrões que revelem informações valiosas sobre os fenômenos em estudo. Na tabela anterior, cada linha representa um evento e sua localização dada pelas coordenadas X e Y. Na rotina da vigilância em saúde, essas coordenadas podem indicar casos de doenças como, por exemplo, chikungunya. Um agrupamento de casos de chikungunya pode sugerir uma abundância de criadouros de mosquitos nas proximidades, o que, por consequência, aciona ações de campo e direciona equipes para áreas críticas. A análise de padrões de pontos é, portanto, uma ferramenta essencial para monitorar riscos, avaliar a eficácia das intervenções e compreender a dinâmica espacial dos eventos de saúde.

Chamamos a análise de dados de pontos de análise de Padrão de Pontos (ou Processos Pontuais). Esta técnica é fundamental para estudar a distribuição espacial de eventos em uma determinada área de estudo. A análise de processos pontuais se inicia com a visualização dos pontos na área de estudo, conforme esquematizado na Figura 5. Nesse exemplo, temos uma área de estudo fictícia com várias localizações pontuais (p1, p2, …, pn).

Figura 5: Área de estudo fictícia com o conjunto de dados consistindo de uma série de localizações pontuais.

Figura 5: Área de estudo fictícia com o conjunto de dados consistindo de uma série de localizações pontuais.

Neste momento, não precisamos nos preocupar com o que cada ponto representa, mas sim com a sua localização e a forma com que estão distribuídos na área de estudo. A Figura acima permite, portanto, visualizar a distribuição espacial dos pontos e avaliar se há padrões. Dessa forma, a partir da visualização dos pontos, podemos começar a investigar o padrão de distribuição dos eventos. No próximo item, exploraremos detalhadamente a importância dessa análise na vigilância em saúde.

Por que é importante?

A análise de padrões pontuais aplica-se a diversos agravos de interesse da vigilância em saúde. Quando examinam a distribuição de casos de tuberculose como pontos em um mapa, por exemplo, conseguem localizar focos prováveis de transmissão e priorizar ações de busca ativa. Do mesmo modo, ao mapearem acidentes de trânsito, identificam trechos viários que demandam maior oferta de ambulâncias e ajustes na sinalização.

Depois de revelarem esses agrupamentos, as equipes conectam a distribuição espacial dos eventos a fatores ambientais, sociais ou econômicos e, a partir daí, conseguem:

• Relacionar a distribuição dos eventos com fatores ambientais, sociais ou econômicos.

• Fazer previsões da ocorrência de eventos futuros em áreas específicas.

• Otimizar recursos de forma mais eficiente, como serviços públicos ou campanhas de saúde.

• Tomar decisões através de políticas públicas e estratégias de planejamento.

Um exemplo concreto ilustra o potencial dessa abordagem. No verão de 2017-2018, registrou-se um surto de hepatite A no município do Rio de Janeiro. Na Figura 6, cada ponto marca um caso suspeito investigado e as estrelas amarelas assinalam os locais onde o vírus da hepatite A foi detectado em amostras de água pelos analistas da Vigilância Epidemiológica. Ao sobreporem esses dados, os analistas visualizaram rapidamente a coincidência entre casos humanos e pontos de contaminação hídrica, reforçando a necessidade de intervenções sanitárias e de comunicação de risco junto às populações mais expostas.

Figura 6: Distribuição espacial de casos suspeitos em uma investigação de surto de hepatite A no Rio de Janeiro no verão de 2017/2018.

Figura 6: Distribuição espacial de casos suspeitos em uma investigação de surto de hepatite A no Rio de Janeiro no verão de 2017/2018.

A partir dessa visualização, pode-se levantar três questões centrais para orientar as próximas análises:

1. Existe algum padrão na distribuição dos casos?

2. O risco é maior próximo às fontes de contaminação?

3. Qual é o provável local de exposição ao vírus?

Neste momento, vamos concentrar primeiro na primeira pergunta. Em uma inspeção visual rápida, podemos identificar que o padrão na distribuição dos casos na Figura 6 difere daquele observado na Figura 5. Na Figura 5, os pontos parecem mais espalhados em toda a área de estudo, enquanto que, na Figura 6, existem alguns agrupamentos de pontos. A partir dessa diferença, podemos discutir agora quais tipos de padrões de distribuição pontual podem ocorrer, de modo a classificar corretamente o cenário observado e selecionar as ferramentas estatísticas adequadas nas próximas etapas.

Vamos, então, conhecer quais são os tipos de padrões de distribuição pontual?

Padrões de Distribuição Pontual

A disposição espacial dos pontos pode ser classificada em três categorias principais:

  • Aleatória: Cada ponto tem a mesma probabilidade de ocorrer em qualquer local, e sua posição não é influenciada pela localização de outros pontos.

  • Regular (ou uniforme): Os pontos estão distribuídos de forma que mantêm, em geral, uma distância aproximadamente uniforme entre si, criando uma disposição quase equidistante.

  • Agrupado (ou cluster): Os pontos estão concentrados em determinadas áreas, formando grupos densos, enquanto outras regiões podem conter poucos ou nenhum ponto.

Veja abaixo na Figura 7 como os diferentes padrões de pontos são representados graficamente nos eixos X e Y:

Figura 7: Padrões espaciais de pontos, a partir de suas coordenadas.

Figura 7: Padrões espaciais de pontos, a partir de suas coordenadas.

Compreendidos os padrões da disposição dos pontos, o próximo passo é investigar como esses padrões se formam. Para isso, vamos conhecer os chamados processos pontuais.

Processos pontuais

Agora, vamos compreender melhor como analisar os dados pontuais. Para interpretar esses padrões, podemos definir dois tipos básicos de processos pontuais:

  1. Processos de primeira ordem: Esses processos referem-se a fenômenos globais ou de grande escala, relacionados às variações no valor médio do processo no espaço. Esse processo é geralmente representado por variações na intensidade ou densidade de pontos no espaço. Para exemplificar um processo de primeira ordem, podemos citar o aumento de casos de dengue em áreas com maior densidade populacional e áreas mais urbanizadas. Para analisar esse fenômeno, utiliza-se frequentemente a estimativa de Kernel para avaliar a média dos eventos e, dessa forma, visualizar regiões com maior ou menor concentração de casos.

  2. Processos de segunda ordem: Esses processos referem-se a fenômenos locais ou de pequena escala, investigam interações entre eventos próximos, avaliando a existência de dependência espacial em uma escala menor, local. O interesse aqui é determinar se os pontos interagem entre si, influenciando a localização uns dos outros. Por exemplo, casos de tuberculose podem ocorrer mais próximos uns dos outros devido à transmissão pessoa a pessoa, gerando pequenas concentrações locais ou clusters. Para investigar esses padrões locais, métodos como a análise dos vizinhos mais próximos ou a Função K são utilizados para verificar se há uma distância típica entre casos próximos, indicando possível interação ou agrupamento.

Além de entender como os pontos se formam, também é preciso avaliar estatisticamente se esses padrões ocorreram ao acaso ou se eles se distribuem de forma regular ou agrupada por influência de algum fator externo. É aqui que entra a análise da completa aleatoriedade espacial (CSR - Complete Spatial Randomness). Em outras palavras, cada evento tem a mesma probabilidade de ocorrer em qualquer lugar dentro da área analisada, sem formar padrões específicos (nem agrupados, nem regulares).

Testar a CSR é justamente avaliar se a distribuição observada é fruto do acaso ou se existe alguma estrutura espacial determinando o padrão encontrado (por exemplo, fontes de contaminação, transmissão interpessoal, características ambientais, entre outras).

Na prática, isso é feito testando-se duas hipóteses estatísticas:

  • Hipótese nula (H0): Os pontos (casos de doenças, acidentes ou outros agravos) estão distribuídos aleatoriamente no espaço, não havendo nenhum fator influenciando sua localização.

  • Hipótese alternativa (H1): Os pontos formam agrupamentos (clusters) ou apresentam-se dispersos de forma regular, sugerindo fatores externos que influenciam sua localização.

A suposição de CSR implica um processo homogêneo de Poisson, significando que todos os locais têm a mesma probabilidade de ocorrência dos eventos.

Por exemplo, se quisermos avaliar se casos de hepatite A estão relacionados a locais específicos de contaminação, primeiro precisamos testar se os casos estão distribuídos aleatoriamente ou não. Se rejeitarmos a hipótese de completa aleatoriedade, isso sugere fortemente que existe algum fator influenciando o padrão observado, reforçando a necessidade de investigação detalhada sobre locais ou fatores ambientais envolvidos.

Simulação de padrões pontuais e contagem em quadrantes

Agora, vamos aprender a simular e testar esses padrões pontuais usando a técnica de distribuição por quadrantes, para comprovar se a distribuição dos eventos é de fato aleatória ou se há evidências de agrupamento ou regularidade.

Figura 8: Disposição espacial dos pontos, levando em consideração três padrões espaciais de distribuição de pontos, destacados em grades com contagens de ocorrências em cada célula.

Figura 8: Disposição espacial dos pontos, levando em consideração três padrões espaciais de distribuição de pontos, destacados em grades com contagens de ocorrências em cada célula.

A Figura 8 apresenta os três padrões espaciais de distribuição de pontos, vistos anteriormente. Além disso, os pontos estão destacados em grades com contagens de ocorrências em cada célula.

  • Aleatório: A distribuição dos pontos parece desordenada, sem uma organização clara ou padrão definido. As contagens por célula variam de forma aleatória, sugerindo uma distribuição espacial sem dependência ou interação entre os pontos.

  • Regular: Os pontos estão distribuídos de maneira uniforme em toda a grade, com contagens similares e bem distribuídas entre as células. Isso indica uma estrutura um pouco mais organizada e também é possível observar um espaçamento quase equidistante entre os pontos.

  • Agregado: Os pontos estão concentrados em áreas específicas, formando clusters com células de contagens mais altas. Algumas regiões da grade possuem alta densidade, enquanto outras apresentam poucas ou nenhuma ocorrência, evidenciando um padrão de agrupamento.

A seguir, vamos aplicar o teste de Completa Aleatoriedade Espacial (CSR) nesses padrões de pontos. Neste momento, apresentaremos apenas os comandos e as interpretações básicas dos resultados. Não se preocupe, pois na seção prática com R detalharemos melhor o funcionamento deste teste.

# Padrão Aleatório
quadrat.test(aleatorio_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 27.043, df = 29, p-value = 0.8613 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

O comando quadrat.test() realiza um teste da Completa Aleatoriedade Espacial (CSR) para um padrão de pontos baseado nas contagens em quadrantes. Por padrão, utiliza o teste qui-quadrado, mas pode realizar testes baseados em Monte Carlo. É usado para verificar se a distribuição dos pontos é uniforme ou segue o modelo esperado.

Para esse padrão dos dados pontuais, o pvalor=0,8613, ou seja, o pvalor<α supondo um α=0,05, indicando que não há evidências suficientes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa.

# PAdrão Regular
quadrat.test(regular_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 16.75, df = 29, p-value = 0.06815 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

Para esse cenário, o pvalor=0,06815, ou seja, também o pvalor>α supondo um α=0,05, indicando que não há evidências suficientes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa.

# Padrãoagregado ou cluster
quadrat.test(agregado_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 164.27, df = 29, p-value < 2.2e-16 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

Já para esse cenário, o pvalor=2,2×1016, ou seja, também o pvalor<α supondo um α=0,05, indicando que há evidências fortes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa.

Na prática da vigilância, um passo possível depois de plotar os casos em um mapa é transformá-los em um produto que revele a intensidade do evento. Uma técnica muito usada para isso é a Estimativa de Densidade por Kernel, também conhecida como mapa de calor, que veremos a seguir.

Estimativa de Densidade de Kernel (Mapa de Calor)

A estimativa de densidade de Kernel é uma ferramenta exploratória utilizada para analisar processos pontuais, permitindo calcular a intensidade das ocorrências em uma determinada região. Esse método gera uma superfície contínua, onde cada valor representa a intensidade de eventos por unidade de área. Essa técnica também é amplamente conhecida por mapa de calor, por representar áreas de concentração de eventos nas quais são utilizadas simbologias de cores quentes para áreas de alta concentração (por exemplo, vermelho) e cores frias para áreas de baixa concentração (azul ou verde).

O método é relativamente simples: essa técnica utiliza uma janela móvel que percorre toda a área de estudo e aplica pesos variáveis a cada ponto, considerando a distância dos pontos dentro da janela ao ponto avaliado: mais perto, peso maior; mais longe, peso menor. Como resultado, cria-se um mapa de calor que revela, de forma suavizada, áreas de alta e baixa intensidade e destacando padrões de concentração ou dispersão. Esse resultado é o mapa de calor que a vigilância utiliza para priorizar ações.

Dessa forma, mesmo locais onde nenhum caso foi registrado recebem uma estimativa, permitindo antecipar riscos, inferir rotas prováveis de propagação e até planejar o uso de recursos.

Por que isso importa para a vigilância?

No Quadro 2 são apresentados alguns exemplos de como a estimativa de densidade de Kernel pode ajudar na análise espacial exploratória na vigilância em saúde. Esses exemplos ilustram como a Estimativa de Densidade de Kernel pode ser aplicada para identificar padrões e direcionar ações de saúde pública.

Quadro 2. Exemplos de usos da estimativa de densidade de kernel.

Exemplo prático Utilidade da Estimativa de Densidade de Kernel
Focos de Aedes aegypti ao longo do verão Destaca bairros de maior intensidade para direcionar equipes de controle vetorial.
Acidentes de trânsito com vítimas graves Evidencia “hot spots” viários para reforçar sinalização ou instalar lombadas eletrônicas.
Mordeduras de escorpião em zona rural Permite localizar criadouros prováveis e orientar campanhas educativas.

Agora, vamos ilustrar o conceito de estimativa de densidade de Kernel aplicada em um processo pontual em uma área de estudo fictícia (Figura 9). Considere que nessa área há uma distribuição pontual de casos de um fenômeno de saúde (imagem da esquerda). Na imagem da direita, temos a representação tridimensional da função Kernel aplicada a um ponto específico s (ponto vermelho). Perceba que em ambas imagens a área de estudo está em perspectiva. O parâmetro τ, geralmente chamado de largura de banda ou bandwidth, regula o raio de influência da função Kernel sobre os pontos vizinhos si. O vetor vermelho k indica a densidade estimada em si, enquanto a superfície curva representa o kernel em si, mostrando a ponderação dos eventos de acordo com a distância ao ponto s.

Figura 9: Conceito de estimativa de densidade de Kernel aplicada em um processo pontual.

Figura 9: Conceito de estimativa de densidade de Kernel aplicada em um processo pontual.

Neste sentido, a densidade da intensidade estimada (λ(s)) em uma localização s é calculada pela fórmula:

λ^(s)=i=1n1τ2k(ssiτ)

para a qual:

  • λ^(s) é a estimativa da intensidade no ponto s (local de interesse).

  • k() é a função Kernel, escolhida para suavizar os dados. Pode ser, por exemplo, uma função Gaussiana ou uniforme.

  • τ é o parâmetro de suavização (largura de banda), que controla o grau de influência dos pontos vizinhos na estimativa.

  • ssi é a diferença entre o ponto s e os pontos observados si.

  • n é o número total de pontos ou eventos observados.

A função Kernel k() calcula a influência dos pontos si ao redor de uma localização s. O parâmetro τ determina a suavização de forma que:

  • Valores altos de τ geram uma superfície mais uniforme, representando padrões globais. Isso pode mascarar áreas críticas ou surtos incipientes por “esconder” os detalhes e ocultar padrões importantes.

  • Valores baixos de τ destacam padrões locais, com menor suavização. Isso pode confundir o que seria apenas um “ruído”, com um agrupamento real e, assim, resultar em um mapa de calor com muitos picos e vales.

A escolha do valor de τ é fundamental, mas o melhor valor dependerá do tamanho da área, da densidade de casos e, sobretudo, da pergunta de saúde pública a ser respondida com a análise, ou seja, o objetivo da análise.

Muito interessante, não é mesmo? Nos próximos itens, entraremos em detalhes que, à primeira vista, parecem mais complicados, mas fazem toda a diferença para não criar artefatos enganosos na rotina da vigilância.

Primeiro, veremos como explorar as larguras de banda do kernel. Em seguida, explicaremos a correção de bordas, ajuste simples que impede que áreas próximas ao limite do mapa sejam subestimadas só porque têm vizinhos “faltando” fora da cena. Depois falaremos sobre as diferenças entre os tipos de kernel e algumas técnicas para cálculo do estimador Kernel.

Fique tranquilo: mostraremos exemplos fáceis, de modo que cada conceito se conecte às decisões tomadas no dia a dia pelos serviços de vigilância em saúde.

Escolhendo a largura de banda

Vamos agora explorar, na prática, como diferentes larguras de banda na Estimativa de Densidade de Kernel afetam a suavização quando nossos dados estão espacialmente clusterizados. No R, podemos testar vários valores com a função density(). Essa função possui alguns parâmetros do Kernel como:

  • Largura de banda (sigma): Define o alcance de suavização do kernel.
  • Tipo de kernel (kernel): Permite escolher o formato do kernel.
  • Correção de bordas (diggle): Ajusta a densidade para considerar bordas da janela de observação.
  • Vetor de pesos (weights): Define pesos diferentes para os pontos.

Neste caso, vamos alterar o valor de sigma na função density() utilizando o objeto agregado que foi criado para os exemplos anteriores. Acompanhe o código abaixo:

kernel_cluster1 <- density(agregado, sigma = 0.03)
kernel_cluster2 <- density(agregado, sigma = 0.08)
kernel_cluster3 <- density(agregado, sigma = 0.15)

# vamos apresentar agora os gráficos em ggplot
library(ggplot2)
# vamos carregar a biblioteca patchwork para
# plotar os gráficos juntos
library(patchwork)


g_den1 <- 
  ggplot(as_tibble(kernel_cluster1), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Largura de banda = 0,03") +
  guides(fill = "none") + 
  theme_void()

g_den2 <- 
  ggplot(as_tibble(kernel_cluster2), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") +
  scale_fill_viridis_c(option = "B") +
  labs(title = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

g_den3 <-
  ggplot(as_tibble(kernel_cluster3), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Largura de banda = 0,15") +
  guides(fill = "none") +
  theme_void()

(g_den1 | g_den2 | g_den3)

Figura 10: Exemplos da aplicação da função de kernel utilizando o padrão de pontos agregado variando as larguras de banda.

Figura 10: Exemplos da aplicação da função de kernel utilizando o padrão de pontos agregado variando as larguras de banda.
  1. kernel_cluster1 <- density(agregado, sigma = 0.03) : Calcula a densidade de Kernel para os dados agregado com largura de banda (σ) igual a 0.03, resultando em maior detalhamento (menos suavização).

  2. kernel_cluster2 <- density(agregado, sigma = 0.08): Calcula a densidade de Kernel para os mesmos dados, mas com largura de banda (σ) igual a 0.08, resultando em uma suavização intermediária.

  3. kernel_cluster3 <- density(agregado, sigma = 0.15): Calcula a densidade de Kernel para os dados com σ=0.15, o que gera uma superfície mais suavizada.

  4. Os gráficos são gerados através dos seguintes argumentos da biblioteca ggplot:

  • as_tibble(kernel_cluster1): Converte os dados de densidade calculados para um formato tibble, compatível com o ggplot2.

  • aes(x, y): Define os eixos X e Y para o gráfico.

  • geom_tile(aes(fill = value)): Cria uma camada de azulejos coloridos (tiles) para representar a densidade (value).

  • geom_point: Adiciona os pontos originais da variável agregada, exibidos em branco para destacar sua posição no mapa de calor.

  • scale_fill_viridis_c(option = "B"): Define uma escala de cor contínua usando a paleta viridis (opção “B”).

  • labs(title): Adiciona título ao gráfico, indicando o valor da largura de banda (parâmetro σ).

  • guides(fill = "none"): Remove a legenda da escala de cores.

  • theme_void(): Remove elementos gráficos como eixos e grades para focar apenas na densidade.

A Figura 10 mostra três mapas de calor gerados pelo método de estimativa de densidade de Kernel, aplicados a diferentes larguras de banda (τ) representadas pelos valores 0,03, 0,08 e 0,15. Cada painel corresponde a uma largura de banda específica:

  • Largura de banda = 0,03: O mapa apresenta alta sensibilidade a variações locais, com áreas de concentração muito definidas e detalhadas. A suavização é mínima, evidenciando pequenos agrupamentos ou hotspots de alta densidade.

  • Largura de banda = 0,08: O aumento da largura de banda reduz a granularidade da análise, resultando em uma distribuição mais suavizada. Os padrões locais começam a se mesclar, destacando áreas de concentração maiores, mas com menos detalhes.

  • Largura de banda = 0,15: Com a maior largura de banda, a suavização é intensa, e os agrupamentos menores se fundem em grandes áreas de alta densidade. Este nível de suavização destaca padrões globais, mas pode ocultar variações locais.

Resumindo, a Figura 10 demonstra como a largura de banda no método Kernel afeta a suavização espacial. Larguras menores enfatizam detalhes locais, enquanto larguras maiores evidenciam padrões globais. A escolha da largura de banda deve equilibrar a necessidade de “capturar” detalhes locais sem perder a “visão geral” da distribuição dos eventos.

O pacote ggplot2 também possui funções próprias que permitem a visualização de estimativas de densidade, incluindo o uso de Kernel espacial. Uma dessas funções é a stat_density2d(), que ajusta o Kernel diretamente na visualização e adiciona automaticamente as linhas de contorno, facilitando a interpretação das áreas de maior ou menor densidade. A largura de banda mais adequada para a estimação do Kernel é determinada automaticamente, através do pacote MASS. Abaixo, vamos comparar a largura de banda “ótima” com uma largura de banda arbitrária, escolhida sem muitos critérios. Acompanhe abaixo:

g_contour <- 
  ggplot(as_tibble(agregado), aes(x, y)) +
  stat_density2d_filled(h = c(1, 1)) + 
  stat_density2d(h = c(1, 1), n = 200, contour_var = "count") + 
  geom_point(color = "white") +
  labs(title = "Largura de banda arbitrária (0,1)") + 
  guides(fill = "none") +
  theme_void() 

# vamos inserir linhas de contorno também

opt_bw <- c(MASS::bandwidth.nrd(agregado$x), MASS::bandwidth.nrd(agregado$y))

g_contour_opt <- 
  ggplot(as_tibble(agregado), aes(x, y)) + 
  stat_density2d_filled(h = opt_bw) + 
  stat_density2d(h = opt_bw, n = 200, contour_var = "count") + 
  geom_point(color = "white") +
  labs(title = "Largura de banda ótima") +
  guides(fill = "none") + 
  theme_void()

(g_contour | g_contour_opt)

Figura 11: Exemplos da aplicação da função de Kernel utilizando a largura de banda arbitrária e a ótima estimada.

Figura 11: Exemplos da aplicação da função de Kernel utilizando a largura de banda arbitrária e a ótima estimada.

Este código compara visualmente a Estimativa de Densidade de Kernel com largura de banda arbitrária e largura de banda otimizada usando ggplot2.

  1. Gráfico 1: g_contour
  • Largura de banda arbitrária: h = c(1, 1).

  • stat_density2d_filled(): Preenche áreas de densidade.

  • stat_density2d(): Adiciona linhas de contorno baseadas na densidade.

  • geom_point(): Destaca os pontos originais em branco.

  1. Gráfico 2: g_contour_opt
  • Largura de banda otimizada: Calculada previamente com a função bandwidth.nrd() do pacote MASS e armazenada em opt_bw.

Na Figura 11 podemos observar que a largura de banda otimizada reflete a distribuição real dos dados com maior precisão, enquanto a largura arbitrária pode gerar resultados mais espúrios.

Mesmo com uma largura de banda bem escolhida, suas estimativas podem ser subestimadas nas periferias do mapa. Por isso, no item seguinte veremos correções de borda, muito útil quando a área de estudo é limitada (por exemplo, um bairro cercado por barreiras geográficas).

Estimativa de Kernel com correção por bordas

Como citado anteriormente, o objetivo da correção por bordas na estimativa de densidade de Kernel é lidar com o viés introduzido nas extremidades da região de estudo. Ou seja, em áreas próximas às bordas, o interpolador Kernel pode saltar para fora da região de interesse, subestimando a densidade real, pois há menos pontos dentro do raio de influência do Kernel comparado ao que ocorre no interior da região.

A correção por bordas lida com esse problema ao considerar apenas a contribuição efetiva do Kernel dentro da região de estudo. Isso é feito normalizando o volume do Kernel sobre a área que está realmente dentro da região.

Para calcular essa estimativa, primeiramente, calculamos o volume sob o Kernel que está efetivamente dentro da região de estudo, representado por:

δτ(s)=R1τ2k(suτ)du

Onde:

  • δτ(s) é o volume sob o Kernel ajustado pela região de interesse.

  • k() é a função Kernel escolhida.

  • su é a diferença entre a localização de interesse (s) e os pontos dentro da região (u).

  • τ é o parâmetro de largura de banda que controla a suavização.

  • R é a região de estudo.

Após calcular essa correção, o estimador de densidade ajustado é dado por:

λ^(s)=1δτ(s)i=1n1τ2k(ssiτ)

Onde:

  • λ^(s) é a estimativa da densidade corrigida.

  • δτ(s) é o fator de correção do Kernel calculado anteriormente.

  • n é o número total de pontos observados.

  • k() é a função Kernel.

  • ssi é a diferença entre a localização de interesse (s) e os pontos observados (si).

  • τ é o parâmetro de largura de banda.

Quando falamos em correção por bordas e diversas fórmulas, pode parecer complicado, mas não se preocupe! A correção por bordas é feita acrescentando o parâmetro diggle = TRUE na função density(), que já vimos. Agora, vamos comparar a função de Kernel utilizando o padrão de pontos agregado e a mesma largura de banda com e sem a correção por bordas. Veja o código abaixo:

kernel_cluster1 <- density(agregado, sigma = 0.08)
kernel_cluster2 <- density(agregado, sigma = 0.08, diggle = TRUE)

# vamos apresentar agora os gráficos em ggplot

g_den1 <- 
  ggplot(as_tibble(kernel_cluster1), aes(x, y)) +
  geom_tile(aes(fill = value)) +
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Sem correção por bordas",
       subtitle = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

g_den2 <- 
  ggplot(as_tibble(kernel_cluster2), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Com correção por bordas", 
       subtitle = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

(g_den1 | g_den2)

Figura 12: Exemplos da aplicação da função de Kernel com e sem a correção por bordas.

Figura 12: Exemplos da aplicação da função de Kernel com e sem a correção por bordas.

Este código compara a estimativa de densidade de Kernel com e sem correção por bordas, utilizando o mesmo conjunto de dados e largura de banda (σ=0.08).

  1. kernel_cluster1 <- density(agregado, sigma = 0.08): Calcula a densidade de Kernel para os dados agregado sem aplicar a correção por bordas.

  2. kernel_cluster2 <- density(agregado, sigma = 0.08, diggle = TRUE): Calcula a densidade de Kernel para os mesmos dados, mas agora com a correção por bordas ativada (diggle = TRUE).

Observe na Figura 12 que a correção por bordas aumentou a intensidade nos pontos na borda inferior e lateral direita. A correção por bordas tende a ajustar a densidade para compensar o viés nas bordas da área de estudo, resultando em estimativas mais precisas para regiões próximas aos limites.

Viu como foi fácil? Em seguida, vamos explorar as diferenças entre tipos de interpolador Kernel e como isso pode impactar a análise.

Diferenças entre as funções de Kernel

A função Kernel é um componente essencial na estimativa de densidade de Kernel, pois define como os pontos vizinhos influenciam a estimativa de densidade em um ponto específico. Mas, diferentes funções de Kernel podem resultar em superfícies de densidade distintas, mesmo com a mesma largura de banda. Muitos softwares (como o QGIS, por exemplo), padronizam o uso de uma só função, apesar que disponibilizar outras opções. Neste curso, veremos três tipos de Kernel: Gaussiano, Quártico e o Disc. É importante entender suas diferenças e o impacto na estimativa de densidade, mesmo com a mesma largura de banda.

Para visualizarmos as diferenças entre as funções de Kernel, vamos aplicar três tipos diferentes de Kernel ao mesmo conjunto de dados (o padrão agregado) e com a mesma largura de banda. Acompanhe o código abaixo e, em seguida, vamos discutir os resultados.

kernel_cluster1 <- density(agregado, kernel = "gaussian", sigma = 0.08)
kernel_cluster2 <- density(agregado, kernel = "quartic", sigma = 0.08)
kernel_cluster3 <- density(agregado, kernel = "disc", sigma = 0.08)

# vamos apresentar agora os gráficos em ggplot

g_den1 <-
  ggplot(as_tibble(kernel_cluster1), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Kernel Gaussiano", 
       subtitle = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

g_den2 <- 
  ggplot(as_tibble(kernel_cluster2), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Kernal Quártico", 
       subtitle = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

g_den3 <- 
  ggplot(as_tibble(kernel_cluster3), aes(x, y)) +
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(agregado),
             color = "white") +
  scale_fill_viridis_c(option = "B") +
  labs(title = "Kernel Disc",
       subtitle = "Largura de banda = 0,08") +
  guides(fill = "none") + 
  theme_void()

(g_den1 | g_den2 | g_den3)

Figura 13: Exemplos da aplicação de diferentes funções de Kernel para o mesmo conjunto de dados e com a mesma largura de banda.

Figura 13: Exemplos da aplicação de diferentes funções de Kernel para o mesmo conjunto de dados e com a mesma largura de banda.

Cálculo das Densidades:

  1. kernel_cluster1 <- density(agregado, kernel = "gaussian", sigma = 0.08): Calcula a densidade de Kernel com a função Gaussiana (a padrão) para os dados agregado, usando largura de banda σ=0.08.

  2. kernel_cluster2 <- density(agregado, kernel = "quartic", sigma = 0.08): Calcula a densidade de Kernel usando a função Quartic (também conhecida como Epanechnikov), com a mesma largura de banda.

  3. kernel_cluster3 <- density(agregado, kernel = "disc", sigma = 0.08): Calcula a densidade de Kernel usando a função Disc, que aplica uma influência uniforme dentro de um raio.

Observando a Figura 13, podemos notar diferenças importantes entre os tipos de Kernel. Vamos analisar cada um deles:

  • O Gaussiano utiliza uma distribuição normal, o que significa que os pontos próximos ao centro do Kernel recebem pesos maiores, mas o decrescimento do peso ocorre de forma contínua e suave à medida que a distância aumenta. As transições de cores são suaves e graduais, refletindo a suavização contínua típica do Kernel Gaussiano. Isso resulta em áreas de maior densidade (em laranja/vermelho) são bem definidas, mas as bordas das áreas têm transições gradativas, o que cria uma aparência mais difusa.

  • O Quártico (também conhecida como Epanechnikov) dá mais peso a pontos próximos do que a pontos distantes, mas o decrescimento do peso é gradual e termina abruptamente em um limite definido (como uma “bolha”). As áreas de alta densidade permanecem bem definidas, mas as transições para áreas de menor densidade são ligeiramente menos difusas que no Kernel Gaussiano. Cria uma suavização intermediária, que destaca os agrupamentos sem perder muita precisão local.

  • O Disc dá peso igual a todos os pontos dentro de um raio fixo e ignora pontos fora desse raio. Isso cria áreas de densidade com contornos abruptos e sem transições suaves. As áreas de alta densidade aparecem como “manchas” com bordas bem definidas, sem transições graduais para áreas de menor densidade. Esse Kernel é ideal para destacar claramente os agrupamentos locais, mas sacrifica a suavidade dos resultados.

Mas, no dia a dia da vigilância em saúde, qual função Kernel devemos escolher? Depende do objetivo! Aqui estão algumas orientações:

  • Gaussiano: se o objetivo for explorar padrões gerais de distribuição dos pontos, o Kernel Gaussiano pode ser mais adequado, pois destaca padrões gerais em grandes áreas.

  • Quártico: se o objetivo for identificar agrupamentos locais, com dados clusterizados, o Kernel Quártico pode ser mais apropriado, pois mantém detalhes locais e balanceia a suavização nas áreas mais distantes.

  • Disc: se o objetivo for detectar áreas “hotspots”, com agrupamentos nítidos, o Kernel Disc pode ser mais apropriado, pois destaca claramente os pontos de alta densidade.

Essas escolhas permitem ajustar a suavização aos objetivos específicos da análise espacial. Mas, a análise utilizando estimadores de Kernel não se limita apenas a suavizar a distribuição dos eventos. Também é possível incorporar atributos e calcular razões entre diferentes eventos, o que pode enriquecer ainda mais a análise espacial. Vamos ver como isso funciona na prática nos próximos itens.

Kernel por atributo (kernel ponderado)

Na rotina da vigilância, nem sempre basta saber onde ocorrem os casos; é crucial relacioná-los a um denominador: por exemplo, população exposta, leitos disponíveis, número de criadouros, entre outros. A Estimativa de Densidade de Kernel resolve isso facilmente: basta atribuir um peso a cada ponto, representando o valor do atributo de interesse. Assim, a estimativa de densidade ponderada é calculada como uma média ponderada dos pontos vizinhos, levando em conta o valor do atributo definido.

Neste sentido, o método de suavização utilizando o Kernel permite incorporar uma covariável (atributo) para refinar a estimativa. Por exemplo, é possível estimar a população por unidade de área ou calcular a razão entre dois Kernels, gerando uma estimativa suavizada de eventos por população.

A fórmula para a estimativa por atributo (yi) é:

λ^(s)=i=1n1τ2k(ssjτ)yi

Onde:

  • λ^(s) é a estimativa do atributo para unidade de área.
  • τ é a largura de banda.
  • yi é o valor do atributo associado a cada ponto i.
  • k é a Função Kernel, que define como os valores dos pontos vizinhos contribuem para a estimativa.

Este tipo de análise permite representar espacialmente tanto a distribuição do atributo (ex.: população) quanto a intensidade de eventos proporcional ao atributo, fornecendo uma visão mais detalhada e ajustada à realidade.

Quadro 3: Exemplo de aplicações de Kernel por atributo.

Atributo Como Pergunta Aplicação
População do setor censitário (habitantes) Atribuindo o número de habitantes ao centroide ou ao centro populacional da área Onde se concentram mais pessoas? Planejar vacinação, larvicida
Eventos / População Calculando a razão de eventos (ex.: casos de doença) em relação à densidade populacional. Qual é o risco por 1.000 hab.? Comparar bairros ajustando pelo tamanho populacional

Mas, como isso funciona na prática? O próximo passo agora é combinar duas dessas superfícies: dividir o kernel de casos pelo kernel de população (ou por outro denominador relevante) para obter uma razão de kernels, isto é, um mapa suavizado de risco ou taxa. No próximo item vamos ver, na prática, como gerar essas duas camadas no R e calcular a razão de forma rápida, usando as mesmas funções que acabamos de comentar.

Razão de Kernel

Até aqui, vimos como gerar uma superfície suavizada para qualquer conjunto de pontos. Na rotina da vigilância, porém, o que mais interessa em determinados momentos é a taxa. Por exemplo, quantos eventos ocorrem para cada habitante (ou para cada leito, criadouro, domicílio visitado, entre outros).

A razão de Kernel faz exatamente isso. É uma técnica utilizada para calcular uma taxa suavizada a partir da divisão de duas estimativas de Kernel. Esse método é especialmente útil em análises espaciais que relacionam eventos com outros eventos (por exemplo, casos e controles) e também relacionar eventos e atributos (por exemplo, a densidade de eventos por população).

A razão de Kernel é a divisão da estimativa de densidade de kernel pela estimativa de densidade de kernel ponderada por um atributo. A fórmula é a seguinte:

λ^(s)=i=1n1τ2k(ssiτ)i=1n1τ2k(ssjτ)yi

Dessa forma, temos que:

  1. Numerador: Representa o alisamento dos eventos por unidade de área, considerando a função Kernel k para distribuir a densidade ao redor dos pontos de interesse si;

  2. Denominador: Representa o alisamento da covariável yi (por exemplo, população) por unidade de área, utilizando a mesma largura de banda τ e função Kernel k;

  3. τ: Parâmetro de suavização (largura de banda) que controla o grau de influência dos pontos vizinhos na estimativa.

  4. yi: Atributo associado a cada ponto i, como o número de habitantes ou outro fator relevante.

  5. si: Localização dos eventos de interesse.

Observação: Para a razão de Kernel também é possível utilizar diferentes larguras de banda no numerador e denominar (em geral maior no denominador para estabilizar mais) e também outro evento pontual como “estimador da população a risco”.



Vamos praticar no R? Nossa pequena tarefa, será criar uma “taxa suavizada”, produzir duas superfícies suavizadas e dividi-las, ponto a ponto. Para fixar o conceito, vamos montar dois conjuntos de eventos no R:

  • casos: pontos gerados de forma clusterizada, simulando uma doença realmente concentrada em alguns focos;

  • controles: pontos distribuídos quase ao acaso, servindo apenas de “fundo” populacional.

O resultado é a razão de Kernel, que reflete diferenças relativas entre os dois padrões:

  • Valores maiores que 1 indicam maior densidade relativa no padrão agregado.

  • Valores menores que 1 indicam menor densidade no padrão agregado em relação ao aleatório.

Acompanhe o código abaixo:

bandwidth <- 0.10
kernel_random <- density(aleatorio, sigma = bandwidth)
kernel_cluster <- density(agregado, sigma = bandwidth)

clu_alea_ratio <- kernel_cluster/kernel_random 

par(mfrow = c(1, 3))
plot(kernel_cluster, main = "Cluster")
plot(agregado, add = T, col = "white", pch = 20)

plot(kernel_random, main = "Aleatório")
plot(aleatorio, add = T, col = "white", pch = 20)

plot(clu_alea_ratio, main = "Razão")

Figura 14: Exemplos da aplicação da função da razão de Kernel utilizando casos clusterizados VS casos aleatórios.

Figura 14: Exemplos da aplicação da função da razão de Kernel utilizando casos clusterizados VS casos aleatórios.

Utilizando a largura de banda de 0.10 (bandwidth <- 0.10) este código utiliza estimativas de densidade de Kernel para calcular e visualizar:

  1. kernel_random <- density(aleatorio, sigma = bandwidth): A densidade de eventos em um padrão aleatório.

  2. kernel_cluster <- density(agregado, sigma = bandwidth): A densidade em um padrão agregado.

  3. clu_alea_ratio <- kernel_cluster / kernel_random: A razão entre as densidades (agregado/aleatório), que resulta em uma análise ajustada ou comparativa.

Na Figura 14, note que o mapa da razão de Kernel (imagem da direita) conserva, em amarelo e vermelho, as regiões em destaque que apareciam como “áreas quentes” no kernel de casos (imagem da esquerda). Isso indica que esses agrupamentos permanecem evidentes mesmo depois da padronização. Em outras palavras, a razão de Kernel permite identificar padrões relativos e destacar áreas de concentração que seriam menos visíveis apenas com as densidades absolutas.

Agora, vamos conhecer os processos pontuais de segunda ordem, que investigam a interação entre os eventos como, por exemplo, a Função K e G. Vamos lá?

Análise de um processo pontual de segunda ordem (funções G e K)

Até agora exploramos técnicas que analisam onde os eventos ocorrem com maior ou menor intensidade, usando estimativas como a densidade por Kernel. Contudo, muitas vezes, na vigilância em saúde, não basta saber se há muitos casos em uma região. Cabe ao analista e ao técnico da vigilância o entendimento se os casos interagem espacialmente uns com os outros, formando agrupamentos reais ou mantendo-se dispersos por algum motivo.

Para responder a esse tipo de indagação, utilizamos métodos chamados de análise de processos pontuais de segunda ordem. Essas abordagens avaliam diretamente as distâncias e relações entre eventos, investigando se há interação espacial significativa. Para isso, empregamos duas ferramentas clássicas e muito importantes, conhecidas como funções G e K.

Essas funções têm sido amplamente utilizadas na vigilância em saúde para exploração inicial de padrões de agregação ou dispersão espacial em uma área. Dessa forma, ajudam a identificar áreas de risco e a entender a dinâmica de doenças e outros fenômenos espaciais.

Nos próximos itens, vamos, primeiramente, conhecer os conceitos. E, mais adiante, vamos aplicá-las na prática de R, utilizando exemplo de dados espaciais, sempre focando no seu uso nas análises da rotina da vigilância em saúde.

Função G - Distância do vizinho mais próximo

A função G é uma ferramenta estatística que mede a distância do vizinho mais próximo (ou seja, o evento mais próximo) em relação a um ponto específico. É útil na vigilância em saúde por ser aplicada na detecção de padrões espaciais, como agrupamentos ou dispersões.

O método do vizinho mais próximo é utilizado para estimar a função de distribuição cumulativa G^(r), que se baseia nas distâncias r entre eventos dentro de uma região de análise.

A função de distribuição cumulativa pode ser estimada empiricamente pela fórmula:

G^(r)=#(d(ui,uj)r)n

Para a qual:

  • d(ui,uj) é a distância entre dois eventos ui e uj.

  • r é o limite de distância considerado.

  • n é o número total de eventos na região de análise.

A análise gráfica de G^(r) serve como uma ferramenta exploratória para identificar a existência de interações espaciais entre eventos. Os seguintes padrões podem ser observados:

  • Um crescimento rápido da função para pequenas distâncias r pode indicar interações entre eventos, sugerindo agrupamento ou padrões de aglomeração em escalas menores.

  • Valores baixos de G^(r) para distâncias pequenas, seguidos de crescimento lento, podem sugerir uma distribuição mais regular e menos interativa entre os eventos.

Figura 15: Estimativas da função G para três diferentes padrões de pontos: Aleatório, Regular e Agregado.

Figura 15: Estimativas da função G para três diferentes padrões de pontos: Aleatório, Regular e Agregado.

Os gráficos da Figura 15 apresentam as estimativas da função de distribuição G^(r) para os seguintes padrões espaciais: Aleatório, Regular e Agregado. Cada gráfico compara o comportamento empírico de G^(r) com a função teórica Gpois(r), que representa um padrão de distribuição aleatório (processo de Poisson). Abaixo está a interpretação de cada caso:

  1. Aleatório (Primeiro Gráfico): O comportamento de G^(r) é muito próximo da função Gpois(r), sugerindo que os eventos não apresentam interação espacial e estão distribuídos de forma aleatória. Pequenas variações são esperadas devido a flutuações empíricas.

  2. Regular (Segundo Gráfico): A curva empírica G^(r) cresce mais lentamente em comparação com Gpois(r), indicando uma distribuição mais espaçada dos eventos. Esse padrão é característico de processos regulares, nos quais os eventos mantêm uma distância mínima entre si, sugerindo repulsão.

  3. Agregado (Terceiro Gráfico): A curva G^(r) cresce mais rapidamente para valores baixos de r em relação a Gpois(r), indicando que os eventos estão agrupados ou formam aglomerações em pequenas distâncias. Este padrão é típico de processos que apresentam interações positivas ou atração entre os eventos.

Embora o método do vizinho mais próximo seja útil para fornecer uma indicação inicial sobre a distribuição espacial dos eventos, ele é limitado a pequenas escalas espaciais, o que pode restringir a análise de padrões em distâncias maiores. Para obter uma visão mais abrangente e efetiva do padrão espacial em escalas maiores, recomenda-se o uso da função k, que permite uma análise mais detalhada ao considerar uma gama mais ampla de distâncias e a interação entre os eventos em diferentes escalas.

Função K de Ripley (ou apenas função K)

A função K, também conhecida como medida de momento de segunda ordem reduzida, é uma ferramenta amplamente utilizada na análise de padrões espaciais. Ela é definida para um processo univariado como:

λK(h)=E(# de eventos contidos até uma distância h de um evento arbitrário),

Onde:

  • λ é a intensidade ou o número médio de eventos por unidade de área, assumido constante na região de estudo.

  • E() é o operador de expectativa.

  • h é a distância considerada.

A fórmula estimada para K(h) é dada por:

K^(h)=An2i=1njiwij1I[xj:d(xi,xj)],

Onde:

  • A é a área da região de análise.

  • n é o número total de eventos.

  • wij é o fator de correção de borda.

  • d(xi,xj) é a distância entre os pontos xi e xj.

A função K mensura quantos eventos estão distribuídos em círculos concêntricos ao redor de um ponto de referência (chamado de ponto focal). Esses círculos partem de um raio inicial igual a zero e aumentam gradativamente até cobrir toda a área de estudo.

Principais características:

  • A função K é cumulativa, representando o número esperado de eventos em círculos de raio t, centrados em cada ponto da região de estudo.

  • A intensidade λ normaliza os resultados, permitindo uma comparação entre diferentes escalas ou regiões.

A Figura 16 ilustra círculos concêntricos ao redor de pontos focais, demonstrando como a função K considera diferentes distâncias para analisar padrões espaciais. Essa análise permite identificar se os eventos seguem um padrão aleatório, regular ou agregado. A distribuição é cumulativa, representando o número esperado de vizinhos em um círculo de raio t centrado em um ponto arbitrário, normalizado pela intensidade λ do padrão de pontos na área de estudo, proporcionando uma ferramenta poderosa para análise em diferentes escalas espaciais.

Figura 16: Representação de Círculos Concêntricos para Análise da Função K.

Figura 16: Representação de Círculos Concêntricos para Análise da Função K.

Padrões Espaciais Detectados pela Função K

A Figura 17 apresenta as curvas da função K(r) para três padrões espaciais: Aleatório, Regular e Agregado. Cada gráfico compara as diferentes estimativas empíricas (K^iso(r), K^trans(r), K^bord(r)) com a função teórica Kpois(r), que corresponde a um padrão de completa aleatoriedade espacial (CSR). A comparação entre as estimativas empíricas e a curva teórica permite diferenciar padrões espaciais. O desvio das curvas empíricas em relação a Kpois(r) revela a natureza dos eventos: aleatórios, regulares ou agregados.

Figura 17: Estimativas da função K para três diferentes padrões espaciais: Aleatório, Regular e Agregado.

Figura 17: Estimativas da função K para três diferentes padrões espaciais: Aleatório, Regular e Agregado.
  • Padrão Aleatório (Gráfico à Esquerda): As curvas empíricas estão próximas de Kpois(r), indicando que os eventos seguem um padrão espacial aleatório, sem tendência de agregação ou repulsão. Isto ocorre pois, se os eventos são distribuídos de forma aleatória, K^(r) permanece próximo ao valor de referência teórico πr2.

  • Padrão Regular (Gráfico Central): As curvas empíricas estão abaixo de Kpois(r), sugerindo repulsão entre os eventos K^(r)<Kpois(r). Isso reflete uma distribuição regular, na qual os eventos mantêm uma distância mínima entre si.

  • Padrão Agregado (Gráfico à Direita): Quando os eventos estão agrupados ou aglomerados, o número de eventos dentro de pequenas distâncias é maior que o esperado para uma distribuição aleatória. Nesse caso, K^(r)>Kpois(r), e a curva da função K está acima da linha de referência, evidenciando a interação positiva entre os eventos.

Detecção de cluster

Entre as técnicas de análise espacial utilizadas em epidemiologia e vigilância em saúde, a detecção de clusters ocupa uma posição especialmente relevante. Essa abordagem envolve a identificação de padrões de aglomeração de eventos pontuais, como os vistos anteriormente, ou regiões onde há um excesso significativo de risco. Esses padrões incluem surtos de doenças, acidentes e outros eventos que demandam atenção especial e ações direcionadas.

Para identificar esses padrões de forma objetiva, é essencial utilizar métodos estatísticos específicos que permitem detectar e quantificar clusters espaciais. Neste curso, veremos dois tipos principais de testes para a detecção de clusters: genéricos e focados.

Testes Genéricos de Detecção de Clusters

Os testes genéricos são aplicados quando não existe uma hipótese prévia sobre a localização de um possível cluster. Esses testes analisam todo o espaço de estudo à procura de áreas com concentração incomum de eventos. Entre os testes genéricos mais utilizados, destacamos:

i) Estatística de varredura de Kulldorff (SaTScan)

Este método utiliza janelas móveis de diferentes tamanhos para identificar regiões com alta incidência de eventos. Pode ser aplicado a modelos estatísticos diversos, como Poisson, Bernoulli ou Normal.

Exemplo prático: detectar áreas onde ocorrem surtos inesperados de doenças, sem que haja uma suposição prévia sobre onde esses clusters possam estar.

ii) Índice I de Moran

O Índice I de Moran mede a autocorrelação espacial global, verificando se há padrões significativos de agrupamento espacial no conjunto de dados. Embora não indique exatamente a localização dos clusters, ele permite confirmar se existe dependência espacial.

Exemplo prático: identificar padrões globais de altas taxas de mortalidade em uma cidade. Voltaremos a discutir esse método mais adiante no curso.

iii) Teste de Knox

O teste de Knox é especialmente útil para detectar clusters espaço-temporais. Ele avalia se eventos próximos no espaço também ocorrem próximos no tempo, indicando padrões que não são resultado do acaso, como epidemias ou surtos.

Esse teste parte da hipótese nula de que as ocorrências dos eventos são independentes tanto no espaço quanto no tempo. Caso contrário, se existir associação espacial e temporal significativa, isso sugere fortemente a presença de um cluster espaço-temporal.

Exemplo prático: identificar se casos de uma epidemia apresentam uma concentração significativa tanto no espaço quanto no tempo.

Observação: Técnicas vistas anteriormente para análise de processos pontuais de segunda ordem, como as funções G e K, também são frequentemente utilizadas em conjunto com essas abordagens para apoiar a detecção de clusters.

Testes Focados de Detecção de Clusters

Ao contrário dos testes genéricos, os testes focados são aplicados quando já existe um local específico de interesse e pretende-se verificar se há um cluster ao redor dele. Esse tipo de análise é indicado especialmente quando existe uma hipótese prévia sobre onde o cluster pode ocorrer. Entre os testes focados, destacamos:

i) Estatística de Varredura Focada de Kulldorff (SaTScan Focado)

Semelhante à versão genérica, esse método testa especificamente a presença de clusters em torno de pontos pré-determinados.

Exemplo prático: investigar se há aumento significativo de casos de câncer ao redor de uma usina nuclear.

Pratica em R

Até aqui, você conheceu diferentes abordagens teóricas sobre processos pontuais. Agora, chegou a hora de aplicarmos esses conceitos com dados reais, utilizando o R.

Nesta parte prática, trabalharemos com dados referentes à ocorrência de homicídios, suicídios e acidentes de trânsito registrados na cidade de Porto Alegre, Rio Grande do Sul. Ao longo deste exercício, vamos explorar como:

  • Preparar os dados espaciais;

  • Aplicar métodos estatísticos para testar a Completa Aletoriedade Espacial (CSR);

  • Analisar processos pontuais de primeiro e segunda ordem

  • Interpretar resultados em um contexto de saúde pública.

Abra o R e siga atentamente as orientações abaixo.

Baixando e preparando os dados

library(tidyverse)
library(spatstat)
library(splancs)

Chamando algumas bibliotecas para as análises:

tidyverse: Um conjunto de pacotes no R (como ggplot2, dplyr, tidyr, entre outros) para manipulação, visualização, e análise de dados. É usado para transformar, organizar e visualizar dados de forma eficiente e intuitiva.

spatstat: Pacote para análise de padrões espaciais, especialmente voltado para processar e modelar pontos georreferenciados, como análise de densidade e estatísticas de pontos em superfícies bidimensionais.

splancs: Pacote para análise de dados espaciais em R, com foco em cálculos de geometria (como polígonos e coordenadas), análise de pontos no espaço e medidas espaciais básicas.

# Lendo os bancos que estão no repositório github
local <- "https://raw.githubusercontent.com/ogcruz/dados_eco_2023/main/dados/"

homic <- read.table(paste0(local, "homic.dat"), col.names = c("x", "y"))
suic <- read.table(paste0(local, "suic.dat"), col.names = c("x", "y"))
acid <- read.table(paste0(local, "acid.dat"), col.names = c("x", "y"))

# Plotando os casos de homicídios em um plano cartesiano

g <- ggplot(homic) + 
  geom_point(aes(x, y, color = "Homicídios"), shape = 1) + 
  labs(color = "")
g

Distribuição Espacial dos Homicídios em Porto Alegre (RS) no plano cartesiano.

Distribuição Espacial dos Homicídios em Porto Alegre (RS) no plano cartesiano.

Este código está realizando as seguintes etapas:

  1. Definindo o local dos dados: A variável local armazena a URL base para acessar arquivos do repositório GitHub.

  2. Lendo os dados: Os arquivos homic.dat, suic.dat, e acid.dat são lidos diretamente da URL. Cada arquivo é tratado como uma tabela e recebe os nomes de colunas x e y, que presumivelmente representam coordenadas espaciais.

  3. Visualização dos homicídios: Criando um gráfico usando o ggplot2, onde os pontos do dataset homic são plotados em um plano cartesiano (x e y) com uma legenda indicando “Homicídios”. Os pontos são representados por um símbolo circular vazio (shape = 1), e a legenda é personalizada removendo o título (labs(color = "")).

Porto Alegre é uma cidade disposta ao longo do eixo norte/sul. O gráfico perdeu a estrutura espacial, ajustando para o tamanho e forma da janela. Por isso é necessário informar ao programa que este tipo de objeto é um objeto espacial e tem uma escala, que deve ser preservada. Vamos fazer isso com transformando-o em um objeto espacial do pacote sf.

library(sf)

A biblioteca sf (simple features) é usada para manipular e analisar dados geoespaciais no R. Ela permite trabalhar com objetos espaciais (como pontos, linhas e polígonos) em formatos padronizados, facilita a integração com bancos de dados geoespaciais e oferece suporte a operações como transformação de projeções, manipulação de geometrias e análise espacial.

# Transformando os pontos em geometria espacial de pontos

homic_sf <- homic |> 
  st_as_sf(coords = c("x", "y"))
suic_sf <- suic |>
  st_as_sf(coords = c("x", "y"))
acid_sf <- acid |>
  st_as_sf(coords = c("x", "y"))

# Repetindo o mesmo gráfico. Repare que agora usamos a função `geom_sf()`:
g <- ggplot() + 
     geom_sf(data = homic_sf, 
             aes(geometry = geometry, color = "Homicídios"), 
             shape = 1) + 
     labs(color = "")
g

Distribuição Espacial dos Homicídios em Porto Alegre (RS) utilizando a geometria espacial.

Distribuição Espacial dos Homicídios em Porto Alegre (RS) utilizando a geometria espacial.

O código está realizando as seguintes ações:

  1. Transformação de dados em objetos espaciais: As tabelas de dados homic, suic, e acid são convertidas em objetos de geometria espacial (pontos) usando a função st_as_sf() do pacote sf. As colunas x e y são usadas como coordenadas para essa conversão. Isso é feito para homic_sf, suic_sf, e acid_sf.

  2. Criação de um gráfico espacial: Um gráfico é criado usando ggplot() e a camada geom_sf() para plotar os dados espaciais de homic_sf. Os pontos são coloridos e rotulados como “Homicídios” no gráfico. O argumento shape = 1 especifica que os pontos devem ser representados por círculos não preenchidos.

O gráfico gerado mostra os pontos espaciais de homic_sf (homicídios) em um mapa ou plano de coordenadas, com a legenda indicando “Homicídios”.

Agora vamos adicionar os pontos referentes a suicídios e acidentes:

g <- g + 
  geom_sf(data = suic_sf, 
          aes(geometry = geometry, color = "Suícidios"), 
          shape = 1) + 
  geom_sf(data = acid_sf, 
          aes(geometry = geometry, color = "Acidentes"), 
          shape = 1)
g

Distribuição Espacial dos Acidentes, Homicídios e Suicídios em Porto Alegre (RS) utilizando a geometria espacial.

Distribuição Espacial dos Acidentes, Homicídios e Suicídios em Porto Alegre (RS) utilizando a geometria espacial.

Este trecho de código adiciona camadas ao gráfico g, que já havia sido criado anteriormente, para incluir dados espaciais de suicídios e acidentes:

suic_sf: Os dados de suicídios (convertidos em geometria espacial anteriormente) são adicionados ao gráfico como uma nova camada usando geom_sf(). Os pontos dessa camada são coloridos e rotulados como “Suicídios”, com a mesma forma (círculos vazados, shape = 1).

acid_sf: Os dados de acidentes são adicionados da mesma forma, com os pontos coloridos e rotulados como “Acidentes”.

O gráfico final (g) agora inclui três conjuntos de pontos espaciais (homicídios, suicídios e acidentes), cada um com uma cor diferente e identificado na legenda.

Agora vamos importar o polígono que corresponde ao contorno de Porto Alegre:

# Contorno de Porto Alegre
contorno.poa <- read.table(paste0(local, "/contpoa.dat"),
                           col.names = c("x", "y"))

# Plotando com a função `geom_polygon`:
g + 
  geom_polygon(data = contorno.poa, aes(x, y), 
               fill = "transparent", color = "black")

Distribuição Espacial dos Acidentes, Homicídios e Suicídios em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Distribuição Espacial dos Acidentes, Homicídios e Suicídios em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Este código lê um arquivo contendo as coordenadas do contorno de Porto Alegre, armazena os dados em contorno.poa e, em seguida, utiliza a função geom_polygon para traçar o contorno no gráfico g, com preenchimento transparente e borda na cor preta.

Os pontos fora do contorno são das ilhas, não devem ser incorporados a análise. Vamos transformar o contorno também em um objeto espacial (st_polygon) para identificar os pontos fora do contorno:

# Para transformar em polígono espacial,
# transformamos primeiro em matriz e em seguida
# em uma lista:

poa_sf <- contorno.poa |>
    as.matrix() |>
    list() |>
    st_polygon()

Este código transforma o objeto contorno.poa em um polígono espacial no formato sf.

  • as.matrix(): Converte os dados em uma matriz de coordenadas.
  • list(): Envolve a matriz em uma lista (requisito para criar polígonos com múltiplos anéis).
  • st_polygon(): Constrói o polígono espacial a partir da lista de coordenadas.

O resultado é um objeto sf representando o contorno como um polígono espacial.

Agora sim, podemos utilizar a função st_within() para identificar os pontos fora do contorno:

# A função st_within() tem essa funcionalidade
homic_sf <- homic_sf |>
    mutate(dentro = lengths(st_within(homic_sf, poa_sf)))

ggplot(homic_sf, aes(geometry = geometry)) + 
  geom_sf(aes(color = as.factor(dentro))) +
  geom_sf(data = poa_sf, fill = "transparent") +
  labs(color = "Dentro do polĩgono")

Distribuição Espacial dos Homicídios em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Distribuição Espacial dos Homicídios em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Este código realiza o seguinte:

  1. Adicionando uma coluna dentro ao dataset homic_sf:
  • Calcula, para cada ponto em homic_sf, se ele está dentro do polígono poa_sf usando st_within().
  • A função lengths() conta quantos polígonos contêm cada ponto (1 se está dentro, 0 se não está).
  1. Criando um gráfico com ggplot:
  • Plota os pontos de homic_sf usando geom_sf(), colorindo-os com base na nova coluna dentro (convertida em fator).
  • Adiciona o polígono poa_sf como uma camada transparente.
  • Define a legenda para indicar “Dentro do polígono”.

Isso resulta em um mapa que visualiza os pontos classificados como dentro ou fora do polígono de referência.

# Filtra somente as observações dentro do polígono
homic_sf2 <- homic_sf |>
    dplyr::filter(dentro == 1)

ggplot(homic_sf2, aes(geometry = geometry)) +
  geom_sf(aes(color = as.factor(dentro))) +
  geom_sf(data = poa_sf, fill = "transparent") +
  labs(color = "Dentro do polĩgono")

Distribuição Espacial dos Homicídios e em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Distribuição Espacial dos Homicídios e  em Porto Alegre (RS) utilizando a geometria espacial com o contorno.

Este comando filtra os pontos espaciais do objeto espacial homic_sf (que contém os pontos de homicídios) para incluir apenas as observações que têm o valor da coluna dentro igual a 1.

E aí construímos novamente o mapa utilizando o objeto homic_sf2 contemplando apenas os pontos dentro do polígono.

Pronto, agora podemos começar a reproduzir algumas análises, que foram vistas na parte teórica a respeito dos padrões pontuais, utilizando o contexto casos de homicídios, suicídios e acidentes de carro em Porto Alegre/RS.

Primeiro, para organizar imagens e apresentá-las juntas, vamos utilizar o pacote gridExtra:

# se não estiver instalado, rodar:
install.packages("gridExtra")
library(gridExtra)

Em seguida, vamos simular alguns padrões dos dados de ponto da ocorrência de homicídios, utilizando como referência o polígono referente ao contorno de Porto Alegre/RS:

set.seed(123)

# Gerando um padrão aleatório
alea_sf <- st_sample(poa_sf, size = 100, type = "random")

g_alea <- ggplot(alea_sf, aes(geometry = geometry)) +
  geom_sf() + 
  geom_sf(data = poa_sf, fill = "transparent") +
  ggtitle("Distribuição aleatória")

# Gerando um padrão regular
uni_sf <- st_sample(poa_sf, size = 100, type = "regular") %>%
  st_as_sf() %>%
  # a função jitter é bastante utilizada e
  # serve para adicionar uma flutuação (desvio)
  # aleatória aos pontos
  st_jitter(amount = 100) %>%
  dplyr::filter(lengths(st_within(., poa_sf)) == 1)

g_uni <- ggplot(uni_sf, aes(geometry = x)) + geom_sf() +
  geom_sf(data = poa_sf, aes(geometry = geometry),
          fill = "transparent") + ggtitle("Distribuição regular")


# Gerando um padrão de cluster
# 1. Criar pontos centrais para os clusters
clusters_centers <- st_sample(poa_sf, size = 5, type = "regular") %>% 
  st_as_sf()

# 2. Adicionar pontos ao redor dos centros dos clusters
cluster_sf <- clusters_centers %>%
  st_coordinates() %>%
  as.data.frame() %>%
  rename(x = X, y = Y) %>%
  mutate(cluster_id = 1:nrow(.)) %>%
  # Adicionar 20 pontos ao redor de cada centro
  group_by(cluster_id) %>%
  do({
    center_x <- .$x
    center_y <- .$y
    n_points <- 20
    tibble(
      x = rnorm(n_points, mean = center_x, sd = 50),
      y = rnorm(n_points, mean = center_y, sd = 50)
    )
  }) %>%
  ungroup() %>%
  st_as_sf(coords = c("x", "y"), crs = st_crs(poa_sf)) %>%
  dplyr::filter(lengths(st_within(., poa_sf)) == 1) # Filtrar apenas pontos dentro do polígono

# Visualizar o padrão de cluster
g_cluster <- ggplot(cluster_sf, aes(geometry = geometry)) +
  geom_sf() +
  geom_sf(data = poa_sf, aes(geometry = geometry),
          fill = "transparent") +
  ggtitle("Distribuição em Clusters")
grid.arrange(g_alea, g_uni, g_cluster, ncol = 3)

Distribuição Espacial dos Homicídios em Porto Alegre (RS) nos diferentes padrões de pontos.

Distribuição Espacial dos Homicídios em Porto Alegre (RS) nos diferentes padrões de pontos.

Este código simula e visualiza diferentes padrões espaciais de dados de pontos (distribuição aleatória, regular e em clusters) dentro de um polígono representando o contorno de Porto Alegre/RS.

  1. Padrão Aleatório
  • st_sample(poa_sf, size = 100, type = "random"): Gera 100 pontos distribuídos aleatoriamente dentro do polígono poa_sf.

  • ggplot2: visualiza os pontos sobrepostos ao contorno do polígono. Resultado: Gráfico com pontos aleatoriamente espalhados.

  1. Padrão Regular
  • Gera uma grade regular de pontos dentro do polígono e aplica um pequeno desvio aleatório para simular uma regularidade imperfeita.

  • st_sample(poa_sf, size = 100, type = "regular"): cria uma grade regular.

  • st_jitter(): adiciona variação (deslocamento aleatório) aos pontos.

  • filter(lengths(st_within(...)) == 1): mantém apenas pontos dentro do polígono.

  1. Padrão em Clusters
  • Simula clusters de pontos ao redor de centros pré-definidos.

  • st_sample(poa_sf, size = 5, type = "regular"): cria 5 centros regularmente distribuídos. Para cada centro, gera 20 pontos ao redor utilizando valores aleatórios normalmente distribuídos (rnorm). Converte coordenadas para o sistema espacial original e filtra pontos dentro do polígono.

  • ggplot2: exibe os clusters com pontos concentrados ao redor de centros.

O código demonstra a criação de três padrões espaciais distintos (aleatório, regular e clusters) usando funções de manipulação e visualização espacial, permitindo análise visual e comparativa.

Testando a Completa Aletoriedade Espacial (CSR)

# Convertendo para a class ppp

alea_ppp <- alea_sf |>
    as.ppp()

uni_ppp <- uni_sf |>
    as.ppp()

cluster_ppp <- cluster_sf |>
    as.ppp()

# Construindo os quadrantes com as respectivas
# contagens
alea_qc <- quadratcount(alea_ppp, nx = 5, ny = 6)
uni_qc <- quadratcount(uni_ppp, nx = 5, ny = 6)
cluster_qc <- quadratcount(cluster_ppp, nx = 5, ny = 6)
quadrat.test(alea_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 53, df = 29, p-value = 0.008416 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

quadrat.test(uni_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 34.789, df = 29, p-value = 0.4231 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

quadrat.test(cluster_qc)
Chi-squared test of CSR using quadrat counts

data:
X2 = 381.39, df = 29, p-value < 2.2e-16 alternative hypothesis: two.sided

Quadrats: 5 by 6 grid of tiles

O objetivo deste código é realizar o teste de completa aleatoriedade espacial (CSR) para três padrões espaciais diferentes (aleatório, regular e em clusters), utilizando quadrantes para contagem de pontos e o teste de χ2 (qui-quadrado) com o pacote spatstat.

  • Os objetos espaciais (alea_sf, uni_sf e cluster_sf) são convertidos para a classe ppp (point pattern dataset in the two-dimensional plane) do pacote spatstat, que é necessária para análises espaciais detalhadas.

  • as.ppp(): Realiza a conversão de objetos da classe sf (Simple Features) para ppp.

  • O espaço de cada padrão é dividido em uma grade 5×6 (30 células ao todo) para contar o número de pontos em cada quadrante.

  • quadratcount(): nx = 5, ny = 6: Divide o espaço em 5 células no eixo x e 6 células no eixo y. Retorna as contagens de pontos em cada célula.

  • O teste de χ2 (qui-quadrado) avalia se os pontos estão distribuídos de forma aleatória no espaço.

  • quadrat.test(): Realiza o teste de CSR para as contagens por quadrante.

Lembrando que:

  • Hipótese nula (H0): Os pontos estão distribuidos aleatoriamente no espaço.

  • Hipótese alternativa (H1): Os pontos formam agrupamentos (clusters) ou estão organizados de maneira dispersa no espaço.

Para padrão aleatório dos dados pontuais, o pvalor=0,008416, ou seja, o pvalor>α, supondo um α=0,05, indica que há evidências suficientes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa (CSR).

Já supondo o padrão regular dos dados pontuais, o pvalor=0,4231, ou seja, também o pvalor>α, supondo um α=0,05, indica que não há evidências suficientes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa (CSR).

Por fim, para esse cenário aglomerado dos dados pontuais, o pvalor=2,2×1016, ou seja, também o pvalor<α, supondo um α=0,05, indica que há evidências fortes para rejeitar a hipótese nula de que o padrão de pontos segue uma distribuição aleatória completa (CSR).

Processo de primeira ordem: Gerando a estimativa de densidade de Kernel (mapa de calor)

Agora iremos verificar o padrão espacial de primeira ordem dos casos dos casos de homicídios, suicídios e acidentes de carro em Porto Alegre/RS.

homic_ppp <- homic_sf2 |>
  as.ppp()
Window(homic_ppp) <- as.owin(poa_sf)

homic_den1 <- density(homic_ppp, sigma = 200, diggle = TRUE)

g_homic_den1 <- ggplot(as_tibble(homic_den1), aes(x, y)) + 
  geom_tile(aes(fill = value)) +
  geom_point(data = as_tibble(homic_ppp), 
             color = "white", shape = 1, size = 0.5) + 
  geom_sf(data = poa_sf, aes(geometry = geometry), 
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Homicídios", subtitle = "sigma = 200") +
  guides(fill = "none") + 
  theme_void()

suic_ppp <- suic_sf |>
  as.ppp()
Window(suic_ppp) <- as.owin(poa_sf)

suic_den1 <- density(suic_ppp, sigma = 200, diggle = TRUE)

g_suic_den1 <- ggplot(as_tibble(suic_den1), aes(x,y)) + 
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(suic_ppp),
             color = "white", shape = 1, size = 0.5) + 
  geom_sf(data = poa_sf, aes(geometry = geometry), 
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Suicídios", subtitle = "sigma = 200") +
  guides(fill = "none") + 
  theme_void()

acid_ppp <- acid_sf |>
  as.ppp()
Window(acid_ppp) <- as.owin(poa_sf)

acid_den1 <- density(acid_ppp, sigma = 200, diggle = TRUE)

g_acid_den1 <- ggplot(as_tibble(acid_den1), aes(x, y)) + 
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(acid_ppp),
             color = "white", shape = 1, size = 0.5) + 
  geom_sf(data = poa_sf, aes(geometry = geometry),
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Acidentes", subtitle = "sigma = 200") +
  guides(fill = "none") + 
  theme_void()

grid.arrange(g_homic_den1, g_suic_den1, g_acid_den1, ncol = 3)

Padrão de Densidade Espacial de Homicídios, Suicídios e Acidentes (Sigma = 200) em Porto Alegre/RS.

Padrão de Densidade Espacial de Homicídios, Suicídios e Acidentes (Sigma = 200) em Porto Alegre/RS.

Este código realiza a análise de densidade de pontos (kernel density estimation) para três conjuntos de dados espaciais (homicídios, suicídios e acidentes) em uma região delimitada, em nosso caso o polígono referente a Porto Alegre/RS, e visualiza os resultados em um painel com três mapas temáticos.

  • Os objetos espaciais homic_sf2, suic_sf e acid_sf são convertidos em objetos de pontos (classe ppp) para análise espacial com o pacote spatstat.

  • A região de análise é definida com a função Window usando os limites do objeto espacial poa_sf.

  • A densidade de pontos é calculada para cada conjunto de dados utilizando a função density do pacote spatstat.

  • O parâmetro sigma = 200 define o raio de suavização, e o argumento diggle = TRUE aplica a correção de borda.

  • Para cada conjunto de dados (homicídios, suicídios e acidentes). Os resultados da densidade são convertidos para o formato de objeto tibble para integração com o ggplot2.

  • É criado um mapa de calor com geom_tile, sobreposto aos pontos originais (com geom_point) e aos limites geográficos da área (geom_sf).

  • A escala de cores é definida com scale_fill_viridis_c, e os títulos e temas são ajustados.

Os três mapas temáticos são dispostos lado a lado em uma grade com a função grid.arrange do pacote gridExtra.

Agora iremos investigar verificar o padrão espacial de segunda ordem dos casos dos casos de homicídios em Porto Alegre/RS utilizando diferentes larguras de banda (σ = 100, 200 e 500 metros).

homic_den2 <- density(homic_ppp, sigma = 100, diggle = TRUE)

g_homic_den2 <- ggplot(as_tibble(homic_den2), aes(x, y)) + 
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(homic_ppp),
             color = "white", shape = 1, size = 0.5) +
  geom_sf(data = poa_sf, aes(geometry = geometry), 
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Homicídios", subtitle = "sigma = 100") +
  guides(fill = "none") + 
  theme_void()

homic_den3 <- density(homic_ppp, sigma = 500, diggle = TRUE)

g_homic_den3 <- ggplot(as_tibble(homic_den3), aes(x, y)) + 
  geom_tile(aes(fill = value)) + 
  geom_point(data = as_tibble(homic_ppp),
             color = "white", shape = 1, size = 0.5) + 
  geom_sf(data = poa_sf, aes(geometry = geometry), 
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Homicídios", subtitle = "sigma = 500") +
  guides(fill = "none") + 
  theme_void()

grid.arrange(g_homic_den2, g_homic_den1, g_homic_den3, ncol = 3)

Mapas de Densidade Espacial de Homicídios com Diferentes Valores de Suavização (sigma = 100, 200 e 500m) em Porto Alegre/RS.

Mapas de Densidade Espacial de Homicídios com Diferentes Valores de Suavização (sigma = 100, 200 e 500m) em Porto Alegre/RS.

Este código irá usar a função density para calcular a densidade kernel espacial dos eventos de homicídio representados pelo objeto homic_ppp (um objeto espacial de pontos).

  • O parâmetro sigma define a largura da suavização (100 no primeiro caso, 200 no segundo e 500 no terceiro).

  • Converte os resultados de densidade kernel (homic_den2 e homic_den3) em tibble para serem usados no ggplot2.

  • Cria mapas de calor (geom_tile) das densidades calculadas, com a escala de cores viridis (opção “B”).

  • Adiciona os pontos originais (homic_ppp) para mostrar a localização dos eventos de homicídio.

  • Sobrepõe os mapas com limites espaciais de um objeto poa_sf (representando um mapa de Porto Alegre), sem preenchimento (fill = "transparent").

  • Remove a legenda de preenchimento (guides(fill = "none")) e aplica um tema minimalista (theme_void()).

Vamos fazer a razão de kernel entre as causas de homicídio e suicídios de Porto alegre/RS:

suic_homic_ratio <- suic_den1/homic_den1

g_suic_homic <- ggplot(as_tibble(suic_homic_ratio), aes(x, y)) + 
  geom_tile(aes(fill = value)) + 
  geom_sf(data = poa_sf, aes(geometry = geometry), 
          fill = "transparent", inherit.aes = FALSE) + 
  scale_fill_viridis_c(option = "B") +
  labs(title = "Razão", subtitle = "Suicídios/Homicídios") +
  guides(fill = "none") + 
  theme_void()

grid.arrange(g_homic_den1, g_suic_den1, g_suic_homic, ncol = 3)

Mapas de Densidade de Homicídios, Suicídios e Razão Suicídios/Homicídios (sigma = 200m) em Porto Alegre/RS.

Mapas de Densidade de Homicídios, Suicídios e Razão Suicídios/Homicídios (sigma = 200m) em Porto Alegre/RS.

Este trecho de código realiza o cálculo da razão de kernel entre dois tipos distintos de pontos (suic_den1 e homic_den1) armazenando o resultado na variável suic_homic_ratio.

Para a criação de um mapa da razão de kernel (g_suic_homic) estamos usando o pacote ggplot2 que mostra a razão de suicídios por homicídios em uma representação espacial.

Processo de segunda ordem: Funções G e K

Verificando o padrão espacial de segunda ordem dos casos de homicíodos em POA/RS:

# se não estiver instalado, rodar:
install.packages("splancs")
library(splancs)
library(splancs)
homic_ppp2 <- as.ppp(homic_sf2$geometry)

plot(homic_ppp2, pch = 19, cex = 0.5)
polymap(contorno.poa, add = T)

Distribuição de Pontos dos Homicídios em Porto Alegre/RS.

Distribuição de Pontos dos Homicídios em Porto Alegre/RS.

Neste trecho do código há a conversão os dados em formato sf (dados espaciais) para o formato ppp (padrão pontual) e construindo o mapa com os eventos.

  • homic_sf$geometry: Estamos extraindo apenas a coluna de geometria de um objeto espacial chamado homic_sf. Essa geometria representa os pontos (localizações dos homicídios).

  • as.ppp(): Converte esses dados de geometria para o formato “padrão de pontos” (point pattern) usado na análise espacial. Esse formato é compatível com as funções do pacote spatstat, amplamente usado para análise de padrões espaciais em R.

  • plot(homic_ppp2, pch = 19, cex = 0.5): Plota o padrão espacial dos pontos (localizações dos homicídios). Com os pontos no formato círculo sólido (pch = 19) e tamanho de pontos cex = 0.5.

  • polymap(contorno.poa, add = T): Desenha o contorno no gráfico do objeto que representa o contorno de Porto Alegre, usado para delimitar visualmente a área de estudo, adicionando o contorno ao gráfico existente (em vez de criar um novo).

par(mfrow = c(1, 2))
plot(envelope(Y = homic_ppp2, fun = Gest, nsim = 9), main = "Funcao G")

Generating 9 simulations of CSR … 1, 2, 3, 4, 5, 6, 7, 8, 9.

Done.

plot(envelope(Y = homic_ppp2, fun = Kest, nsim = 9), main = "Funcao K")

Generating 9 simulations of CSR … 1, 2, 3, 4, 5, 6, 7, 8, 9.

Done.

Análise do Padrão Espacial: Funções G e K para Homicídios em Porto Alegre/RS.

Análise do Padrão Espacial: Funções G e K para Homicídios em Porto Alegre/RS.
  • par(mfrow = c(1, 2)): Ajusta a janela gráfica para exibir dois gráficos lado a lado (1 linha, 2 colunas).

  • plot(envelope(Y = homic_ppp2, fun = Gest, nsim = 9)): Calcula e plota a função G com simulações de CSR gerando os envelopes simulados para comparar a função observada com um padrão aleatório do padrão de pontos referente aos homicídios.

  • plot(envelope(Y = homic_ppp2, fun = Kest, nsim = 9): Calcula e plota a função K com simulações de CSR gerando os envelopes simulados para comparar a função observada com um padrão aleatório do padrão de pontos referente aos homicídios.

Os dois gráficos (funções G e K) sugerem que os homicídios em Porto Alegre (RS) apresentam um padrão agrupado em vez de uma distribuição aleatória. Esse padrão indica que há concentrações de homicídios em determinadas áreas, o que pode estar associado a fatores socioeconômicos, geográficos ou outros. Para uma análise mais aprofundada, seria necessário investigar as causas do agrupamento.

Considerações finais

Neste módulo, você aprendeu a manipular e analisar dados espaciais pontuais utilizando o R. A partir de exemplos práticos, exploramos técnicas essenciais para descrever visualmente e analisar estatisticamente esses eventos espaciais. Vimos como realizar estimativas de densidade espacial, avaliar padrões por meio da técnica de Kernel, e testar hipóteses sobre aleatoriedade ou dependência espacial, ferramentas que nos permitem identificar se os pontos estão agrupados ou dispersos no espaço.

A análise de padrões pontuais mostrou-se uma abordagem poderosa para explorar a distribuição espacial dos eventos, ajudando a vigilância em saúde a obter insights valiosos sobre fenômenos epidemiológicos e situações críticas como surtos de doenças, acidentes ou outros eventos importantes. Ao identificar áreas com concentrações significativas, podemos tomar decisões mais informadas, direcionar recursos e implementar estratégias de intervenção adequadas.

Em resumo, entender como eventos estão distribuídos no espaço, identificando padrões de agrupamento (clusters) ou confirmando sua completa aleatoriedade, é fundamental para compreender melhor os fenômenos em estudo, permitindo ações mais efetivas no contexto da vigilância em saúde.

Referências

• BIVAND, Roger S. et al. Applied spatial data analysis with R. New York: Springer, 2013.

• DIGGLE, P. J. Overview of statistical methods for disease mapping and its relationship to cluster detection. In: ELLIOTT, P.; WAKEFIELD, Jon; BEST, Nicola; BRIGGS, David. Spatial Epidemiology: Methods and Application. Oxford: Oxford University Press, 2001. p. 87-103.

• GATRELL, Anthony C. et al. Spatial point pattern analysis and its application in geographical epidemiology. Transactions of the Institute of British geographers, p. 256-274, 1996.

• WAKEFIELD, Jon; KELSALL, J. E.; MORRIS, S. E. Clustering, cluster detection, and spatial variation in risk. In: ELLIOTT, P.; WAKEFIELD, Jon; BEST, Nicola; BRIGGS, David. Spatial Epidemiology: Methods and Application. Oxford: Oxford University Press, 2001. p. 128-152.